
package galcon.players;

import galcon.utils.Circle;
import galcon.utils.Constants;
import galcon.utils.Point;
import galcon.visuals.components.Fleet;
import galcon.visuals.components.Planet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;


public class Human extends Player implements MouseListener, MouseWheelListener, MouseMotionListener{

    protected Planet[] planets;

    //Human can send from multiple sources
    protected int[] selectedPlanetsID;
    protected long timeLastSelected;

    //Current mouseover target
    protected int mouseOverPlanetID;

    //Dest plaent
    protected int destPlanetID;

    //Current percentage to send
    protected double sendPercentage;

    public Human(int playerID, Color playerColor){
        super(playerID, playerColor);
        initMouseVars();
    }

    protected void initMouseVars(){
        this.sendPercentage = 0.5;
        this.mouseOverPlanetID = -1;
        this.destPlanetID = -1;
    }

    public void drawCursor(Graphics g){
        this.drawSelected(g);
        this.drawMouseOver(g);
        this.drawLines(g);
        this.drawPercentageSend(g);
    }

    protected void drawPercentageSend(Graphics g){
        String temp = "";
        temp += this.sendPercentage;

        g.setColor(Color.WHITE);
        g.drawString(temp, 0, 10);
    }

    protected void drawSelected(Graphics g){
        if(this.selectedPlanetsID != null){
            for(int i = 0 ; i < this.selectedPlanetsID.length; i++){
                //Draw a yellow circle of pixels 4
                Planet planet = this.planets[this.selectedPlanetsID[i]];
                Circle circle = planet.getCircle();
                Point point = circle.getPoint();
                int radius = circle.getRadius();

                //Now Draw
                g.setColor(Color.YELLOW);
                g.drawOval(point.getX() - radius, point.getY() - radius,
                        radius * 2, radius * 2);

            }
        }
    }

    protected void drawMouseOver(Graphics g){
        if(this.mouseOverPlanetID != -1){
            Circle circle = this.planets[this.mouseOverPlanetID].getCircle();
            Point point = circle.getPoint();
            int radius = circle.getRadius();

            //Now Draw
            g.setColor(Color.RED);
            g.drawOval(point.getX() - radius, point.getY() - radius, radius * 2, radius * 2);
        }
    }

    protected void drawLines(Graphics g){
        if(this.mouseOverPlanetID != -1 && this.selectedPlanetsID != null){
            //Draw lines from each selected planet to destination planet
            Circle destCircle = this.planets[this.mouseOverPlanetID].getCircle();

            for(int i = 0; i < this.selectedPlanetsID.length; ++i){

                if(this.selectedPlanetsID[i] == this.mouseOverPlanetID){
                    continue;
                }

                //Lets make source start at source
                Circle sourceCircle = this.planets[this.selectedPlanetsID[i]].getCircle();
                double deltaX = destCircle.getPoint().getX() - sourceCircle.getPoint().getX();
                double deltaY = destCircle.getPoint().getY() - sourceCircle.getPoint().getY();
                double angleToDest = Math.atan2(deltaY, deltaX);
                double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
                distance -= destCircle.getRadius();

                //System.out.println("/////////////////////////");
                //System.out.println("Angle: " + angleToDest + " | Sin: " + Math.sin(angleToDest) + " | Cos: "+ Math.cos(angleToDest));
                //System.out.println(sourceCircle);

                Point start =  new Point((int)(sourceCircle.getPoint().getX() + sourceCircle.getRadius() * Math.cos(angleToDest)),
                        (int)(sourceCircle.getPoint().getY() + sourceCircle.getRadius() * Math.sin(angleToDest)));
                Point end = new Point((int)(sourceCircle.getPoint().getX() + distance * Math.cos(angleToDest)),
                        (int)(sourceCircle.getPoint().getY() + distance * Math.sin(angleToDest)));

                //System.out.println("Start: x: " + start.getX() + " y: " + start.getY());
                //System.out.println("End: x: " + end.getX() + " y: " + end.getY());

                //Now draw
                g.setColor(Color.YELLOW);
                g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
            }
        }
    }

    public Command getCommand(Planet[] planets, Fleet[] fleets){
        //Store the planets for user selection
        this.planets = planets;


        return null;

    }

    public void mouseWheelMoved(MouseWheelEvent e){

        //This is negated because getWheelRotation() returns negative away
        double deltaPercentage = -e.getWheelRotation()/100.0;
        this.sendPercentage += deltaPercentage;

        //Constrain
        if(this.sendPercentage < 0.01){
            this.sendPercentage = 0.01;
        }else if(this.sendPercentage > 1.0){
            this.sendPercentage = 1.0;
        }
        
        
        //Remove all the nasty decimals
        //Not sure if they's a better way
        this.sendPercentage *= 100;
        this.sendPercentage = Math.floor(sendPercentage);
        this.sendPercentage /= 100;

    }

    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
    public void mousePressed(MouseEvent e){}
    public void mouseReleased(MouseEvent e){}
    public void mouseDragged(MouseEvent e){}

    //Select currentTarget, check if already double click
    public void mouseClicked(MouseEvent e){
        if(this.planets == null) return;
        if(this.mouseOverPlanetID == -1) return;

        if(this.planets[this.mouseOverPlanetID].getOwnerID() == this.playerID){
            if((System.currentTimeMillis() - this.timeLastSelected < Constants.DOUBLE_CLICK_TIMEOUT) &&
                    (selectedPlanetsID.length == 1)){
                //Now Select all
                ArrayList<Integer> ownedPlanets = new ArrayList<Integer>();
                for(int i = 0; i < this.planets.length; ++i){
                    if(this.planets[i].getOwnerID() == this.playerID){
                        ownedPlanets.add(i);
                    }
                }

                this.selectedPlanetsID = new int[ownedPlanets.size()];
                for(int i = 0; i < this.selectedPlanetsID.length; i++){
                    this.selectedPlanetsID[i] = ownedPlanets.get(i);
                }

            }else{
                //Make a new selection
                this.timeLastSelected = System.currentTimeMillis();
                this.selectedPlanetsID = new int[1];
                this.selectedPlanetsID[0] = this.mouseOverPlanetID;
            }
        }else if(this.selectedPlanetsID != null){
            //Choose a dest
            this.destPlanetID = this.mouseOverPlanetID;
        }
    }

    //Find current mouseover target
    public void mouseMoved(MouseEvent e){
        if(this.planets == null) return;

        int x = e.getX();
        int y = e.getY();

        for(int i = 0; i < this.planets.length; ++i){
            Point point = this.planets[i].getCircle().getPoint();
            int radius = this.planets[i].getCircle().getRadius();

            int deltaX = point.getX() - x;
            int deltaY = point.getY() - y;

            double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

            if(distance < radius){
                this.mouseOverPlanetID = i;
                return;
            }
        }
        //No planet selected
        this.mouseOverPlanetID =  -1;
    }
}
